// =======================================================================================
/*!
 * @file    Util.h
 *
 * @brief   General utility functions.
 *
 * @author  Jorge Ramos (jramos at pobox dot com).
 *
 * @version 1.0.0.0 - May 23, 2011.
 *          @li Initial version.
 *
 * @remarks Copyright (c) 2011 Jorge Ramos.
 *
 * @remarks This software is provided 'as-is', without any express or implied warranty.
 *          Use it at your own risk. In no event shall the authors or copyright holders
 *          be held liable for any damages arising from the use of this software. Use
 *          and redistribution in source and binary forms, with or without modification,
 *          are permitted. Altered source versions must be plainly marked as such.
 *
 * @remarks This software is distributed in the hope that it will be useful, but WITHOUT
 *          ANY WARRANTY.
 */
// =======================================================================================

#ifndef _Util_H_DA9444C9_6649_11DF_B321_0003FFCCBD00_
#define _Util_H_DA9444C9_6649_11DF_B321_0003FFCCBD00_

#ifdef _MSC_VER
#pragma once
#endif

//////////////////////////////////////////////////////////////////////////////////////////

#include "Defs.h"

//////////////////////////////////////////////////////////////////////////////////////////

#ifdef __cplusplus
extern "C" {
#endif

//////////////////////////////////////////////////////////////////////////////////////////

#ifndef _countof
#define _countof(array) (sizeof (array) / sizeof (array [0]))
#endif

#ifndef UNREFERENCED_PARAMETER
#define UNREFERENCED_PARAMETER(p) ((VOID) (p))
#endif

//////////////////////////////////////////////////////////////////////////////////////////

__inline BOOL IsCharDriveSep (INT ch) { return ch == _T (':'); }
__inline BOOL IsCharPathSep (INT ch) { return ch == _T ('\\') || ch == _T ('/'); }
__inline BOOL IsCharDriveOrPathSep (INT ch) { return IsCharDriveSep (ch) || IsCharPathSep (ch); }

//////////////////////////////////////////////////////////////////////////////////////////

VOID SetApplicationInstance (HINSTANCE hInstance);
VOID SetApplicationName (LPCTSTR pszApplicationName);
VOID SetApplicationVersion (LPCTSTR pszApplicationVersion);
VOID SetApplicationAuthor (LPCTSTR pszApplicationAuthor);
VOID SetApplicationNotice (LPCTSTR pszApplicationNotice);

HINSTANCE GetApplicationInstance (VOID);
LPCTSTR GetApplicationName (VOID);
LPCTSTR GetApplicationVersion (VOID);
LPCTSTR GetApplicationAuthor (VOID);
LPCTSTR GetApplicationNotice (VOID);

INT _vsnwprintf2 (LPWSTR pszBuffer, size_t nCount, LPCWSTR pszFormat, va_list pArgs);
INT _snwprintf2 (LPWSTR pszBuffer, size_t nCount, LPCWSTR pszFormat, ...);
INT _vsnprintf2 (LPSTR pszBuffer, size_t nCount, LPCSTR pszFormat, va_list pArgs);
INT _snprintf2 (LPSTR pszBuffer, size_t nCount, LPCSTR pszFormat, ...);

#ifdef _UNICODE
#define _vsntprintf2 _vsnwprintf2
#define _sntprintf2 _snwprintf2
#else
#define _vsntprintf2 _vsnprintf2
#define _sntprintf2 _snprintf2
#endif

INT FormatTextVaW (LPWSTR pszBuffer, size_t nCount, LPCWSTR pszFormat, va_list pArgs);
INT FormatTextW (LPWSTR pszBuffer, size_t nCount, LPCWSTR pszFormat, ...);
INT FormatTextVaA (LPSTR pszBuffer, size_t nCount, LPCSTR pszFormat, va_list pArgs);
INT FormatTextA (LPSTR pszBuffer, size_t nCount, LPCSTR pszFormat, ...);
INT FormatTextAnsiW (LPSTR pszBuffer, size_t nCount, LPCWSTR pszFormat, ...);
INT FormatTextAnsiA (LPSTR pszBuffer, size_t nCount, LPCSTR pszFormat, ...);
INT FormatTextUnicodeW (LPWSTR pszBuffer, size_t nCount, LPCWSTR pszFormat, ...);
INT FormatTextUnicodeA (LPWSTR pszBuffer, size_t nCount, LPCSTR pszFormat, ...);

#ifdef _UNICODE
#define FormatText FormatTextW
#define FormatTextVa FormatTextVaW
#define FormatTextAnsi FormatTextAnsiW
#define FormatTextUnicode FormatTextUnicodeW
#else
#define FormatText FormatTextA
#define FormatTextVa FormatTextVaA
#define FormatTextAnsi FormatTextAnsiA
#define FormatTextUnicode FormatTextUnicodeA
#endif

VOID DisplayInformation (LPCTSTR pszFormat, ...);
VOID DisplayError (LPCTSTR pszFormat, ...);

INT FormatWin32Message (DWORD dwMessageId, LPTSTR pszBuffer, size_t nCount);
VOID DisplayWin32Message (DWORD dwMessageId, LPCTSTR pszMessageSource);

INT FormatSystemMessage (INT nErrno, LPTSTR pszBuffer, size_t nCount);
VOID DisplaySystemMessage (INT nErrno, LPCTSTR pszMessageSource);

//////////////////////////////////////////////////////////////////////////////////////////

#define TRACE_OUTPUT_NONE       0
#define TRACE_OUTPUT_DEBUG      1
#define TRACE_OUTPUT_FILE       2
#define TRACE_OUTPUT_ANSI       4
#define TRACE_OUTPUT_CHKBOM     8

#define YYTRACE Trace
#define NOTRACE 1 ? (VOID) 0 : Trace

#ifdef _DEBUG
#define TRACE Trace
#else
#define TRACE 1 ? (VOID) 0 : Trace
#endif

VOID SetTraceOutput (UINT nFlag);
UINT GetTraceOutput (VOID);
VOID OutputTraceString (LPCTSTR pszText);
VOID TraceVa (LPCTSTR pszFormat, va_list pArgs);
VOID Trace (LPCTSTR pszFormat, ...);
VOID TraceWin32Message (DWORD dwMessageId, LPCTSTR pszMessageSource);
VOID TraceSystemMessage (INT nErrno, LPCTSTR pszMessageSource);
BOOL Win32Call (BOOL bResult, LPCTSTR pszFunctionName);

//////////////////////////////////////////////////////////////////////////////////////////

#define SYSCALL(n,s) do { if ((n) == -1) { DisplaySystemMessage (errno, s); exit (3); } } while (0)

#define WIN32CALL(b,s) do { if (! (b)) { DisplayWin32Message (GetLastError (), s); exit (3); } } while (0)

//////////////////////////////////////////////////////////////////////////////////////////

#ifdef __cplusplus
}
#endif

//////////////////////////////////////////////////////////////////////////////////////////
// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx

EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)

//////////////////////////////////////////////////////////////////////////////////////////

#endif

// =======================================================================================
